// Copyright (c) 2023 Shanghai Bosch Rexroth Hydraulics & Automation Ltd.

// #include <getopt.h>
#include "json.hpp"
// #include <ncurses.h>
#include <curl/curl.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/cloud_viewer.h>
#include <string>
#include <unistd.h> //for sleep() at   void Bosch::startLocal()
#include <iostream> //for licensingFeatureGetHostId
#include <fstream>  //for licensingFeatureGetHostId
#include <chrono>

// #include <assert.h>
// #include <netdb.h>
// #include <arpa/inet.h>
// #include <netinet/tcp.h>
// #include <vector>h
// #include <unistd.h>
// #include <memory.h>
// #include <sstream>
// #include <bitset>

using Json = nlohmann::json;
bool local_flag = false;
std::string hostId;

/* ******************************* libcurl, post json info.********************************** */
class HttpClient
{
public:
  HttpClient();
  ~HttpClient();

public:
  static size_t receive_data(void *contents, size_t size, size_t nmemb, void *stream);
  // http post
  static CURLcode HttpPost(const std::string &strUrl, std::string szJson, std::string &strResponse, int nTimeout);
};

CURLcode HttpClient::HttpPost(const std::string &strUrl, std::string szJson, std::string &strResponse, int nTimeout)
{
  CURLcode res;
  char szJsonData[10240]; // for licensingFeatureSet change from 1024 to 10240
  memset(szJsonData, 0, sizeof(szJsonData));
  strcpy(szJsonData, szJson.c_str());
  CURL *pCURL = curl_easy_init();
  struct curl_slist *headers = NULL;
  if (pCURL == NULL)
  {
    return CURLE_FAILED_INIT;
  }

  CURLcode ret;
  ret = curl_easy_setopt(pCURL, CURLOPT_URL, strUrl.c_str());
  //    std::cout << ret << std::endl;

  ret = curl_easy_setopt(pCURL, CURLOPT_POST, 1L);
  headers = curl_slist_append(headers, "Expect:");
  headers = curl_slist_append(headers, "content-type:application/json");
  ret = curl_easy_setopt(pCURL, CURLOPT_HTTPHEADER, headers);
  ret = curl_easy_setopt(pCURL, CURLOPT_POSTFIELDS, szJsonData);
  // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
  ret = curl_easy_setopt(pCURL, CURLOPT_TIMEOUT, nTimeout);
  ret = curl_easy_setopt(pCURL, CURLOPT_WRITEFUNCTION, HttpClient::receive_data);
  ret = curl_easy_setopt(pCURL, CURLOPT_WRITEDATA, (void *)&strResponse);
  res = curl_easy_perform(pCURL);
  curl_easy_cleanup(pCURL);
  return res;
}

size_t HttpClient::receive_data(void *contents, size_t size, size_t nmemb, void *stream)
{
  std::string *str = (std::string *)stream;
  (*str).append((char *)contents, size * nmemb);
  return size * nmemb;
}

typedef unsigned long long Size;

/* *****************************Struct********************************************** */
typedef struct Timestamp
{
  bool valid;
  int64_t time;
  double resolution; // number, must be one of 1, 100, 1000, 1000000, or 1000000000
} Timestamp;

typedef struct Pose3D
{
  double x;  // absolute x coordinate in map frame
  double y;  // absolute y coordinate in map frame
  double z;  // z coordinate
  double qw; // quaternion w (real) coordinate
  double qx; // quaternion x coordinate
  double qy; // quaternion y coordinate
  double qz; // quaternion z coordinate
} Pose3D;

typedef struct Transform3D
{
  double x;  // absolute x coordinate in map frame
  double y;  // absolute y coordinate in map frame
  double z;  // z coordinate
  double qw; // quaternion w (real) coordinate
  double qx; // quaternion x coordinate
  double qy; // quaternion y coordinate
  double qz; // quaternion z coordinate
} Transform3D;

typedef struct Pose2D
{
  double x;
  double y;
  double a;
} Pose2D;

typedef struct PointCluster
{
  Pose2D prototype;
  Size fromIndex;
  Size toIndex;
} PointCluster;

typedef struct Container
{
  std::string content;
  std::string contentEncoding;
  std::string contentMediaType;
} Container;

/*  ************************************JSON RPC command******************************* */
class Locator
{
public:
  Locator(std::string host_name, std::string username, std::string password);
  ~Locator();
  // 7.2 Session Control  (Module: Session)
  // 7.2.1 sessionLogin： Login to a product element
  bool sessionLogin(int port);
  // 7.2.2 sessionLogout
  bool sessionLogout(int port, std::string session_id);

  // 7.3 Diagnostic Information (Module: Diagnostic)
  // 7.3.1 Retrieves all available diagnostic entries from the buffer
  bool diagnosticList();
  // 7.3.2 diagnosticClear Clears the diagnostic buffer, removing all stored diagnostic entries
  bool diagnosticClear();

  // 7.4 Software Licensing (Module: LicensingFeature)
  // 7.4.2 licensingFeatureGetHostId：  Retrieves the hardware-specific host ID.
  bool licensingFeatureGetHostId();
  // 7.4.3 licensingFeatureSet: Sends a software license to the product element.
  bool licensingFeatureSet(std::string binfilename);

  // 7.5 System Configuration
  // 7.5.1 configList
  bool configList();
  // 7.5.2 configSet : Sets all configurable parameters to the given values.
  bool configSet_string(std::string key, std::string value);
  bool configSet_num(std::string key, double value);
  bool configSet_bool(std::string key, bool value);
  // TODO 将输入int 改为list，保证多条线的输入
  bool configSet_array(std::string key, std::vector<int> line_data);

  // 8.1 Recording (Module: ClientRecording) .
  // 8.1.1 Requests to start recording laser scans of the environment, which can later beassem-bled into a map.
  bool clientRecordingStart(std::string recordingName);
  // 8.1.2 clientRecordingStop:Requests to stop recording data.
  bool clientRecordingStop();
  // 8.1.3 clientRecordingStartVisualRecording
  bool clientRecordingStartVisualRecording(std::string recordingName);
  // 8.1.4 clientRecordingStopVisualRecording
  bool clientRecordingStopVisualRecording();

  // 8.3 Client Localization (Module: ClientLocalization)
  // 8.3.1 clientLocalizationStart
  bool clientLocalizationStart();
  // 8.3.2 clientLocalizationStop
  bool clientLocalizationStop();
  bool clientLocalizationSwitch(bool flag);
  // 8.3.3 clientLocalizationReset
  bool clientLocalizationReset();
  // 8.3.4 clientLocalizationSetSeed
  bool clientLocalizationSetSeed(double x, double y, double a);

  // 8.4  Manual Map Alignment (Module: ClientManualAlign)
  // 8.4.1 clientManualAlignStart : Requests to enter manual map alignment mode.
  bool clientManualAlignStart();
  // 8.4.2 clientManualAlignStop : Requests to leave manual map alignment mode.
  bool clientManualAlignStop();
  // 8.4.4 clientManualAlignSet :  Manually aligns a map, transforming it into the given reference frame.
  bool clientManualAlignSet(int x, int y, int a, std::string mapname);

  // 8.6.1 & 8.6.2 MaskingStart/Stop :Requests to enter/leave the control mode MASK
  bool clientLaserMaskingStart();
  bool clientLaserMaskingStop();

  // 8.6.3 clientLaserMaskingGetScan : Retrieves the next laser scan available to the Localization Client.
  bool clientLaserMaskingGetScan();

  // 8.7 User Account Management (Module: ClientUser)
  // 8.7.3 clientUserChangePassword： Changes a user’s password stored in the Localization Client.
  bool clientUserChangePassword(std::string newpassword);

  // 9.1 Server-side Map Management (Module: ServerMap)
  // 9.1.1 serverMapGetInfo : Returns all information about a given map
  bool serverMapGetInfo(std::string mapname);
  // 9.1.2 serverMapList : Requests a list of all maps mananged by the map server.
  bool serverMapList();
  // 9.1.5 serverMapGetMap: Retrieves a point cloud representation of a map managed by the ROKIT Locator Server.
  bool serverMapGetMap(std::string server_map_name);

  // 9.1.7 serverMapGetImageWithResolution :Retrieves a raster image of the map with a given image resolution.
  bool serverMapGetImageWithResolution(std::string server_map_name, double resolution);

  // 10.1 Support Report(Module: SupportReport)
  // 10.1.1/10.1.5   bool supportReportCreateAndGetPath();: Creates a new support report that documents the current system state.
  bool supportReportCreateAndGetPath();
  bool supportReportCreate();
  bool supportReportGetPath(std::string report_name);
  bool supportReportList();

public:
  std::string username_{""};
  std::string password_{""};
  std::string host_name_{""};
  int port_{8080};
  std::string session_id_{""};
  int id_{0};
};

Locator::Locator(std::string host_name, std::string username, std::string password)
{
  host_name_ = host_name;
  username_ = username;
  password_ = password;
  session_id_ = "";
}

Locator::~Locator()
{
  session_id_ = "";
}

// base 64 encode
const char *base64_chars[2] = {
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789"
    "+/",

    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789"
    "-_"};

// base 64 encode
std::string base64_encode(unsigned char const *bytes_to_encode, size_t in_len, bool url)
{

  size_t len_encoded = (in_len + 2) / 3 * 4;

  unsigned char trailing_char = url ? '.' : '=';

  //
  // Choose set of base64 characters. They differ
  // for the last two positions, depending on the url
  // parameter.
  // A bool (as is the parameter url) is guaranteed
  // to evaluate to either 0 or 1 in C++ therfore,
  // the correct character set is chosen by subscripting
  // base64_chars with url.
  //
  const char *base64_chars_ = base64_chars[url];

  std::string ret;
  ret.reserve(len_encoded);

  unsigned int pos = 0;

  while (pos < in_len)
  {
    ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0xfc) >> 2]);

    if (pos + 1 < in_len)
    {
      ret.push_back(base64_chars_[((bytes_to_encode[pos + 0] & 0x03) << 4) + ((bytes_to_encode[pos + 1] & 0xf0) >> 4)]);

      if (pos + 2 < in_len)
      {
        ret.push_back(base64_chars_[((bytes_to_encode[pos + 1] & 0x0f) << 2) + ((bytes_to_encode[pos + 2] & 0xc0) >> 6)]);
        ret.push_back(base64_chars_[bytes_to_encode[pos + 2] & 0x3f]);
      }
      else
      {
        ret.push_back(base64_chars_[(bytes_to_encode[pos + 1] & 0x0f) << 2]);
        ret.push_back(trailing_char);
      }
    }
    else
    {

      ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0x03) << 4]);
      ret.push_back(trailing_char);
      ret.push_back(trailing_char);
    }

    pos += 3;
  }

  return ret;
}

// base 64 decode
static const std::string base64_chars_decode =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789+/";

// base 64 encode
static inline bool is_base64(const char c)
{
  return (isalnum(c) || (c == '+') || (c == '/'));
}

// base 64 encode
std::string base64_decode(std::string const &encoded_string)
{
  int in_len = (int)encoded_string.size();
  int i = 0;
  int j = 0;
  int in_ = 0;
  unsigned char char_array_4[4], char_array_3[3];
  std::string ret;

  while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_]))
  {
    char_array_4[i++] = encoded_string[in_];
    in_++;
    if (i == 4)
    {
      for (i = 0; i < 4; i++)
        char_array_4[i] = base64_chars_decode.find(char_array_4[i]);

      char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
      char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
      char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

      for (i = 0; (i < 3); i++)
        ret += char_array_3[i];
      i = 0;
    }
  }
  if (i)
  {
    for (j = i; j < 4; j++)
      char_array_4[j] = 0;

    for (j = 0; j < 4; j++)
      char_array_4[j] = base64_chars_decode.find(char_array_4[j]);

    char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
    char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
    char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

    for (j = 0; (j < i - 1); j++)
      ret += char_array_3[j];
  }

  return ret;
}

// 7.2.1 sessionLogin
bool Locator::sessionLogin(int port)
{
  std::cout << "--> Do sessionLogin" << std::endl;
  // std::cout<<"Different Module has different Session_ID";
  std::string port_str = std::to_string(port);
  // check if port is correct
  switch (port)
  {
    // Refer to table 68 default port definition in API documentation
  case 8080:
    std::cout << "Port is 8080 and you can operate Chapter 7 Common RPC Methods & Chapter 8 Locator Client RPC Methods "
              << std::endl;
    break;
  case 8082:
    std::cout << "Port is 8082 and you can operate Chapter 7 Common RPC Methods & Chapter 9 Locator Server RPC Methods "
              << std::endl;
    break;
  case 8084:
    std::cout << "Port is 8084 and you can operate Chapter 10 JSON RPC ROKIT Locator Client Support "
              << std::endl;
    break;
  case 8086:
    std::cout << "Port is 8086 and you can operate Chapter 10 JSON RPC ROKIT Locator Server Support "
              << std::endl;
    break;
  }
  // set json info
  Json timeout;
  timeout["valid"] = false;
  timeout["time"] = 86400;
  timeout["resolution"] = 1;
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "sessionLogin";
  request["params"]["query"]["timeout"] = timeout;
  request["params"]["query"]["userName"] = username_;
  request["params"]["query"]["password"] = password_;

  // post json info
  std::string str_url = "http://" + host_name_ + ":" + port_str;
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);
  // std::cout << "session login response: \n" << str_response << std::endl;

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      session_id_ = json_response["result"]["response"]["sessionId"];
      std::cout << "sessionLogin Success. "
                << std::endl;
      std::cout << "SessionId is " << session_id_ << std::endl;
      return true;
    }
    else
    {
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 7.2.2 sessionLogout
bool Locator::sessionLogout(int port, std::string session_id)
{
  std::cout << "--> Do sessionLogout" << std::endl;

  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "sessionLogout";
  request["params"]["query"]["sessionId"] = session_id;

  // post json info
  std::string str_url = "http://" + host_name_ + ":" + std::to_string(port);
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);
  // std::cout << "session login response: \n" << str_response << std::endl;

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "sessionLogout Success. \n"
                << std::endl;
      return true;
    }
    else
    {
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 7.3.1 diagnosticList
bool Locator::diagnosticList()
{
  std::cout << "--> Do diagnosticList \n"
            << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "diagnosticList";
  request["params"]["query"]["sessionId"] = session_id_;

  // post json info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);
  // std::cout<< str_response<<std::endl;

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      auto key_value = json_response["result"]["response"]["diagnosticEntries"];
      for (int i = 0; i < key_value.size(); i = i + 1)
      {

        double unix_timestamps = key_value[i]["timestamp"]["time"].get<double>();
        time_t diagnos_info_time = unix_timestamps / 1000;
        std::cout << "    Time（UTC/GMT+08:00）" << ctime(&diagnos_info_time) << std::endl;
        std::cout << "    " << key_value[i] << std::endl;
        std::cout << "\n"
                  << std::endl;
      }
      std::cout << "    diagnosticList Success. \n"
                << std::endl;

      return true;
    }
    else
    {
      std::cout << "    diagnosticList Failed." << std::endl;
      std::cout << "    diagnosticList response: \n"
                << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 7.3.2 diagnosticClear
bool Locator::diagnosticClear()
{
  std::cout << "--> Do diagnosticClear \n"
            << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "diagnosticClear";
  request["params"]["query"]["sessionId"] = session_id_;

  // post json info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    diagnosticClear Success. \n"
                << std::endl;
      return true;
    }
    else
    {
      std::cout << "    diagnosticClear Failed." << std::endl;
      std::cout << "    diagnosticClear response: \n"
                << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 7.4.2 licensingFeatureGetHostId
bool Locator::licensingFeatureGetHostId()
{
  std::cout << "--> Do licensingFeatureGetHostId \n"
            << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "licensingFeatureGetHostId";
  request["params"]["query"]["sessionId"] = session_id_;

  // post json info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      hostId = json_response["result"]["response"]["hostId"];
      std::cout << "    licensingFeatureGetHostId Success. \n"
                << std::endl;
      std::cout << "    hostId is " << hostId << "\n"
                << std::endl;
      return true;
    }
    else
    {
      std::cout << "    licensingFeatureGetHostId Failed." << std::endl;
      std::cout << "    licensingFeatureGetHostId response: \n"
                << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 7.4.3 licensingFeatureSet
bool Locator::licensingFeatureSet(std::string binfilename)
{
  std::cout << "--> Do licensingFeatureSet \n"
            << std::endl;
  std::cout << "    If this programm stuck here, check if the name of binfile is correct and in the same folder ." << std::endl;
  // change bin file to base64 code
  std::ifstream is(binfilename, std::ifstream::binary);
  // get length of file:
  is.seekg(0, is.end);
  unsigned int length = is.tellg();
  is.seekg(0, is.beg);
  char *buffer = new char[length];
  is.read(buffer, length);
  const std::string myString(buffer, length);
  std::string binfileencode = base64_encode(reinterpret_cast<const unsigned char *>(myString.c_str()), myString.length(), false);
  // set json info

  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "licensingFeatureSet";
  request["params"]["query"]["sessionId"] = session_id_;
  request["params"]["query"]["licenseKey"]["contentEncoding"] = "base64";
  request["params"]["query"]["licenseKey"]["contentMediaType"] = "application/LicenseFile";
  request["params"]["query"]["licenseKey"]["content"] = binfileencode;
  // std::cout<<request.dump()<<std::endl;

  // post json info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    licensingFeatureSet Success. \n"
                << std::endl;
      return true;
    }
    else
    {
      std::cout << "    licensingFeatureSet Failed." << std::endl;
      std::cout << "    licensingFeatureSet response: \n"
                << str_response << std::endl;

      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 7.5.1 configList
bool Locator::configList()
{
  std::cout << "--> Do configList. " << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "configList";
  request["params"]["query"]["sessionId"] = session_id_;

  // post json info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // print  response info
  // std::cout << "configlist response: \n" << str_response << std::endl;

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);

    // output config data
    auto key_value = json_response["result"]["response"]["configEntries"];
    std::cout << "    Config info from Locator. (Related information on page 44/129 at APIDpcument 1.1 )\n"
              << std::endl;
    for (int i = 0; i < key_value.size(); i = i + 1)
    {
      std::cout << "    " << key_value[i] << std::endl;
    }
    // std::cout<<typeid(key_value).name()<<std::endl;
    // cout particular key or value if necessary
    /*
    std::cout<<key_value[1]["key"]<<std::endl;
    std::cout<<key_value[1]["value"]<<std::endl;
    std::cout<<typeid(key_value).name()<<std::endl;
    */

    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "\n    configlist Success. \n"
                << std::endl;
      return true;
    }
    else
    {
      std::cout << "    configList Failed." << std::endl;
      std::cout << "    configList response: \n"
                << str_response << std::endl;

      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 7.5.2 configSet string
bool Locator::configSet_string(std::string key, std::string value)
{
  // Config Param info from Locator. (Related information on page 44/129 at APIDpcument 1.1)
  std::cout << "--> Do configSet (Type == AsciiCharacterString || string || NetworkAddress ). "
            << std::endl;

  // set json info
  Json confparam_string;
  confparam_string["key"] = key;
  confparam_string["value"] = value;

  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "configSet";
  request["params"]["query"]["sessionId"] = session_id_;
  request["params"]["query"]["configEntries"] = Json::array({confparam_string});

  // post json info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  std::string str_request;
  // std::cout<< request.dump()<<std::endl;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // print  response info
  // std::cout << "configlist response: \n" << str_response << std::endl;

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    configSet_string Success. Now config method is" << confparam_string["key"] << ", config value is " << confparam_string["value"] << ".\n"
                << std::endl;
      return true;
    }
    else
    {
      std::cout << "    configSet_string Failed. " << std::endl;
      std::cout << "    configSet_string response: \n"
                << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 7.5.2 configSet number
bool Locator::configSet_num(std::string key, double value)
{
  // Config Param info from Locator. (Related information on page 44/129 at APIDpcument 1.1)
  std::cout << "--> Do configSet (Type == IEEE754Double || NonnegativeInteger64 ). \n"
            << std::endl;

  // set json info
  Json confparam_num;
  confparam_num["key"] = "odometry_handler.laser_T_odo.x";
  confparam_num["value"] = -0.15;

  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "configSet";
  request["params"]["query"]["sessionId"] = session_id_;
  request["params"]["query"]["configEntries"] = Json::array({confparam_num});

  // post json info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  std::string str_request;
  // std::cout<< request.dump()<<std::endl;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // print  response info
  // std::cout << "configlist response: \n" << str_response << std::endl;

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    configSet_num Success. Now config method is" << confparam_num["key"] << ", config value is " << confparam_num["value"] << ".\n"
                << std::endl;
      return true;
    }
    else
    {
      std::cout << "    configSet_num Failed. " << std::endl;
      std::cout << "    configSet_num response: \n"
                << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 7.5.2 configSet bool
bool Locator::configSet_bool(std::string key, bool value)
{
  // Config Param info from Locator. (Related information on page 44/129 at APIDpcument 1.1)
  std::cout << "--> Do configSet (Type == bool ). "
            << std::endl;

  // set json info
  Json confparam_bool;
  confparam_bool["key"] = key;
  confparam_bool["value"] = value;

  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "configSet";
  request["params"]["query"]["sessionId"] = session_id_;
  request["params"]["query"]["configEntries"] = Json::array({confparam_bool});

  // post json info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  std::string str_request;
  // std::cout<< request.dump()<<std::endl;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // print  response info
  // std::cout << "configlist response: \n" << str_response << std::endl;

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    configSet_bool Success. Now config method is" << confparam_bool["key"] << ", config value is " << confparam_bool["value"] << ".\n"
                << std::endl;
      return true;
    }
    else
    {
      std::cout << "    configSet_bool (bool) Failed. " << std::endl;
      std::cout << "    configSet_bool response: \n"
                << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 7.5.2 configSet array
bool Locator::configSet_array(std::string key, std::vector<int> line_data)
{
  // Config Param info from Locator. (Related information on page 44/129 at APIDpcument 1.1)
  std::cout << "--> Do configSet (Type == arrya of IEEE754Double ). "
            << std::endl;

  // set json info
  auto range_line = Json::array();
  auto length = line_data.size();

  for (int i = 0; i < length; i = i + 1)
  {
    int val = line_data[i];
    range_line.push_back(val);
  };

  Json confparam_array;
  confparam_array["key"] = key;
  confparam_array["value"] = range_line;
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "configSet";
  request["params"]["query"]["sessionId"] = session_id_;
  request["params"]["query"]["configEntries"] = Json::array({confparam_array});

  // post json info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  std::string str_request;
  // std::cout<< request.dump()<<std::endl;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // print  response info
  // std::cout << "configlist response: \n" << str_response << std::endl;

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    configSet_array Success. Now config method is" << confparam_array["key"] << ", config value is " << confparam_array["value"] << ".\n"
                << std::endl;
      return true;
    }
    else
    {
      std::cout << "    configSet_array (array) Failed. " << std::endl;
      std::cout << "    configSet_array response: \n"
                << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 8.1.1 clientRecordingStart
bool Locator::clientRecordingStart(std::string recordingName)
{
  std::cout << "--> Do clientRecordingStart. "
            << std::endl;

  // set json info

  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "clientRecordingStart";
  request["params"]["query"]["sessionId"] = session_id_;
  request["params"]["query"]["recordingName"] = recordingName;

  // post json info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    clientRecordingStart Success. \n"
                << std::endl;
      return true;
    }
    else if (response_code == 13)
    {
      std::cout << "    clientRecordingStart Failed (Code == 13). \n"
                << std::endl;
      std::cout << "   A required sensor was not available. Connect Lidar first."
                << "\n\n"
                << "   " << str_response << std::endl;
      return false;
    }
    else if (response_code == 10)
    {
      std::cout << "    clientRecordingStart Failed (Code == 10). \n"
                << std::endl;
      std::cout << "    Tried to create an entity that already exists. Change the name of recordingName. \n\n"
                << "    " << str_response << "\n"
                << std::endl;
      return false;
    }
    else
    {

      std::cout << "    clientRecordingStart Failed. \n"
                << std::endl;
      std::cout << "   clientRecordingStart response: \n"
                << "   " << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 8.1.2 clientRecordingStop
bool Locator::clientRecordingStop()
{
  std::cout << "--> Do clientRecordingStop. "
            << std::endl;

  // set json info

  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "clientRecordingStop";
  request["params"]["query"]["sessionId"] = session_id_;

  // post json info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    clientRecordingStop Success. \n"
                << std::endl;
      return true;
    }
    else if (response_code == 7)
    {
      std::cout << "    clientRecordingStop Failed (Code == 7). \n"
                << std::endl;
      std::cout << "    The current system state does not allow the operation to complete. Start Recording first. \n\n"
                << "     " << str_response << std::endl;
      return false;
    }
    else
    {
      std::cout << "     clientRecordingStop Failed. \n"
                << std::endl;
      std::cout << "    clientRecordingStop response: \n"
                << "    " << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 8.1.3 clientRecordingStartVisualRecording
bool Locator::clientRecordingStartVisualRecording(std::string recordingName)
{
  std::cout << "--> Do clientRecordingStartVisualRecording. "
            << std::endl;

  // set json info

  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "clientRecordingStartVisualRecording";
  request["params"]["query"]["sessionId"] = session_id_;
  request["params"]["query"]["recordingName"] = recordingName;

  // post json info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    clientRecordingStartVisualRecording Success. \n"
                << std::endl;
      return true;
    }
    else if (response_code == 13)
    {
      std::cout << "    clientRecordingStartVisualRecording Failed (Code == 13). \n"
                << std::endl;
      std::cout << "   A required sensor was not available. Connect Lidar first. \n\n"
                << "   " << str_response << std::endl;
      return false;
    }
    else if (response_code == 10)
    {
      std::cout << "    clientRecordingStartVisualRecording Failed (Code == 10). \n"
                << std::endl;
      std::cout << "    Tried to create an entity that already exists. Change the name of recordingName. \n\n"
                << "    " << str_response << std::endl;
      return false;
    }
    else
    {

      std::cout << "    clientRecordingStartVisualRecording Failed. \n"
                << std::endl;
      std::cout << "   clientRecordingStartVisualRecording response: \n\n"
                << "   " << str_response << "\n"
                << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 8.1.4 clientRecordingStopVisualRecording
bool Locator::clientRecordingStopVisualRecording()
{
  std::cout << "--> Do clientRecordingStopVisualRecording. "
            << std::endl;

  // set json info

  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "clientRecordingStopVisualRecording";
  request["params"]["query"]["sessionId"] = session_id_;

  // post json info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    clientRecordingStartVisualRecording Success. \n"
                << std::endl;
      return true;
    }
    else if (response_code == 7)
    {
      std::cout << "    clientRecordingStopisualRecording Failed (Code == 7). \n"
                << std::endl;
      std::cout << "    The current system state does not allow the operation to complete. Start Recording first. \n"
                << "     " << str_response << std::endl;
      return false;
    }
    else
    {
      std::cout << "     clientRecordingStopVisualRecording Failed. \n"
                << std::endl;
      std::cout << "    clientRecordingStopVisualRecording response: \n"
                << "    " << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 8.3.1 clientLocalizationStart
bool Locator::clientLocalizationStart()
{
  std::cout << "--> Do clientLocalizationStart" << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "clientLocalizationStart";
  request["params"]["query"]["sessionId"] = session_id_;

  // post JSON info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  // std::cout << request << "\n";
  // std::cout << request.dump() << "\n";
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);
  // std::cout << "switch localization response: " << str_response << std::endl;

  // get error or necessary info
  Json json;
  try
  {
    json = Json::parse(str_response);
    int response_code = json["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "clientLocalizationStart Success." << std::endl;
      return true;
    }
    else
    {
      std::cout << "clientLocalizationStart Failed." << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 8.3.2 clientLocalizationStop
bool Locator::clientLocalizationStop()
{
  std::cout << "--> Do clientLocalizationStop" << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "clientLocalizationStop";
  request["params"]["query"]["sessionId"] = session_id_;

  // post JSON info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  // std::cout << request << "\n";
  // std::cout << request.dump() << "\n";
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);
  // std::cout << "switch localization response: " << str_response << std::endl;

  // get error or necessary info
  Json json;
  try
  {
    json = Json::parse(str_response);
    int response_code = json["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "clientLocalizationStop Success." << std::endl;
      return true;
    }
    else
    {
      std::cout << "clientLocalizationStop Failed." << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// clientLocalizationSwitch
bool Locator::clientLocalizationSwitch(bool local_flag)
{
  std::cout << "--> Do clientLocalizationSwitch. \n"
            << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  if (local_flag == true)
  {
    request["method"] = "clientLocalizationStop";
  }
  else
  {
    request["method"] = "clientLocalizationStart";
  }
  request["params"]["query"]["sessionId"] = session_id_;

  // post JSON info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  std::cout << request << "\n";
  std::cout << request.dump() << "\n";
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);
  // std::cout << "switch localization response: " << str_response << std::endl;

  // get error or necessary info
  Json json;
  try
  {
    json = Json::parse(str_response);
    int response_code = json["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    clientLocalizationSwitch Success. Now " << request["method"] << "\n"
                << std::endl;
      if (request["method"] == "clientLocalizationStop")
      {
        local_flag = false;
      }
      else
      {
        local_flag = true;
      }
      return true;
    }
    else
    {
      std::cout << "    clientLocalizationSwitch Failed. " << std::endl;
      std::cout << "    post clientLocalizationSwitch method is " << request["method"] << std::endl;
      std::cout << "    clientLocalizationSwitch: " << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 8.3.3 clientLocalizationReset
bool Locator::clientLocalizationReset()
{
  std::cout << "--> Do clientLocalizationReset" << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "clientLocalizationReset";
  request["params"]["query"]["sessionId"] = session_id_;

  // post JSON info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  // std::cout << request << "\n";
  // std::cout << request.dump() << "\n";
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);
  // std::cout << "switch localization response: " << str_response << std::endl;

  // get error or necessary info
  Json json;
  try
  {
    json = Json::parse(str_response);
    int response_code = json["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "clientLocalizationReset Success." << std::endl;
      return true;
    }
    else
    {
      std::cout << "clientLocalizationReset Failed." << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 8.3.4 clientLocalizationSetSeed
bool Locator::clientLocalizationSetSeed(double x, double y, double a)
{
  std::cout << "--> Do clientLocalizationSetSeed. \n"
            << std::endl;

  // first define Pose2D
  Pose2D pose;
  pose.x = x;
  pose.y = y;
  pose.a = a;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "clientLocalizationSetSeed";
  request["params"]["query"]["sessionId"] = session_id_;
  request["params"]["query"]["enforceSeed"] = true;
  request["params"]["query"]["seedPose"]["x"] = pose.x;
  request["params"]["query"]["seedPose"]["y"] = pose.y;
  request["params"]["query"]["seedPose"]["a"] = pose.a;

  // post JSON info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);
  // std::cout << "SetSeed response: " << str_response << std::endl;

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    clientLocalizationSetSeed Success.\n"
                << std::endl;
      return true;
    }
    else
    {
      std::cout << "    clientLocalizationSetSeed Failed. " << std::endl;
      std::cout << "    clientLocalizationSetSeed response: \n"
                << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 8.3.3 clientLocalizationReset

// 8.4.1 clientManualAlignStart
bool Locator::clientManualAlignStart()
{
  std::cout << "--> Do clientManualAlignStart \n"
            << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "clientManualAlignStart";
  request["params"]["query"]["sessionId"] = session_id_;

  // post json info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    clientManualAlignStart Success. \n"
                << std::endl;
      return true;
    }
    else
    {
      std::cout << "    clientManualAlignStart Failed." << std::endl;
      std::cout << "    clientManualAlignStart response: \n"
                << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 8.4.2 clientManualAlignStop
bool Locator::clientManualAlignStop()
{
  std::cout << "--> Do clientManualAlignStop \n"
            << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "clientManualAlignStop";
  request["params"]["query"]["sessionId"] = session_id_;

  // post json info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {

      std::cout << "    clientManualAlignStop Success. \n"
                << std::endl;
      return true;
    }
    else
    {
      std::cout << "    clientManualAlignStop Failed." << std::endl;
      std::cout << "    clientManualAlignStop response: \n"
                << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 8.4.4 clientManualAlignSet
bool Locator::clientManualAlignSet(int x, int y, int a, std::string mapname)
{
  Pose2D testali;
  testali.x = 10;
  testali.y = 5;
  testali.a = 0.8;

  std::cout << "--> Do clientManualAlignSet \n"
            << std::endl;
  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "clientManualAlignSet";
  request["params"]["query"]["sessionId"] = session_id_;
  request["params"]["query"]["NEWalignOLD"]["x"] = testali.x;
  request["params"]["query"]["NEWalignOLD"]["y"] = testali.y;
  request["params"]["query"]["NEWalignOLD"]["a"] = testali.a;
  request["params"]["query"]["clientMapName"] = mapname;
  // post json info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {

      std::cout << "    clientManualAlignSet Success. \n"
                << std::endl;

      return true;
    }
    else if (response_code == 12)
    {
      std::cout << "   clientManualAlignSet Failed! (response_code ==12)" << std::endl;
      std::cout << "    clientManualAlignSet response: \n"
                << str_response << std::endl;
      std::cout << "    incorrect mape name . \n"
                << std::endl;
      return false;
    }
    else if (response_code == 7)
    {
      std::cout << "   clientManualAlignSet Failed! (response_code ==7)" << std::endl;
      std::cout << "    clientManualAlignSet response: \n"
                << str_response << std::endl;
      std::cout << "    first operate clientManualAlignStart. \n"
                << std::endl;
      return false;
    }
    else if (response_code == 10)
    {
      std::cout << "   clientManualAlignSet Failed! (response_code ==10)" << std::endl;
      std::cout << "    clientManualAlignSet response: \n"
                << str_response << std::endl;
      std::cout << "    Align already setted. \n"
                << std::endl;
      return false;
    }
    else
    {
      std::cout << "    clientManualAlignSet Failed." << std::endl;
      std::cout << "    clientManualAlignSet response: \n"
                << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 8.6.1 clientLaserMaskingStart
bool Locator::clientLaserMaskingStart()
{
  std::cout << "--> Do clientLaserMaskingStart. \n"
            << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "clientLaserMaskingStart";
  request["params"]["query"]["sessionId"] = session_id_;

  // post JSON info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);
  // std::cout << "clientLaserMaskingStart response: " << str_response << std::endl;

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    clientLaserMaskingStart Success. \n"
                << std::endl;
      return true;
    }
    else if (response_code == 2)
    {
      std::cout << "    clientLaserMaskingStart Failed! " << std::endl;
      std::cout << "    clientLaserMaskingStart response: \n"
                << str_response << std::endl;
      std::cout << "    connect Lidar first, after recieve the laser scan then you can start MAKING. \n"
                << std::endl;
      return false;
    }
    else
    {
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 8.6.2 clientLaserMaskingStop
bool Locator::clientLaserMaskingStop()
{
  std::cout << "--> Do clientLaserMaskingStop. \n"
            << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "clientLaserMaskingStop";
  request["params"]["query"]["sessionId"] = session_id_;

  // post JSON info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);
  // std::cout << "clientLaserMaskingStart response: " << str_response << std::endl;

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    clientLaserMaskingStop Success. \n"
                << std::endl;
      return true;
    }
    else
    {
      std::cout << "    clientLaserMaskingStop Failed. " << std::endl;
      std::cout << "    clientLaserMaskingStop response: \n"
                << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 8.6.3 clientLaserMaskingGetScan
bool Locator::clientLaserMaskingGetScan()
{
  std::cout << "--> Do clientLaserMaskingGetScan. \n"
            << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "clientLaserMaskingGetScan";
  request["params"]["query"]["sessionId"] = session_id_;

  // post JSON info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);
  // std::cout << "clientLaserMaskingGetScan response: " << str_response << std::endl;

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);

    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      // cout the inportant data
      std::cout << "    Some Important info about this Masking Scan" << std::endl;
      std::cout << "    maxRange is " << json_response["result"]["response"]["maxRange"] << std::endl;
      std::cout << "    numBeams is " << json_response["result"]["response"]["numBeams"] << std::endl;
      std::cout << "    Scan time is " << json_response["result"]["response"]["timeStart"]["time"] << "\n"
                << std::endl;
      std::cout << "    clientLaserMaskingGetScan Success. \n"
                << std::endl;
      return true;
    }
    else if (response_code == 7)
    {
      std::cout << "    clientLaserMaskingGetScan Failed! \n " << std::endl;
      std::cout << "    clientLaserMaskingGetScan response: " << str_response << "\n"
                << std::endl;
      std::cout << "    Possible Reason: Lack of step 1:Connect Lidar or 2:start MAKING,after that operate step3: GetScan Masking \n"
                << std::endl;
      return false;
    }
    else
    {
      std::cout << "    clientLaserMaskingGetScan Failed! \n"
                << std::endl;
      std::cout << "    clientLaserMaskingGetScan response: " << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 8.7.3 clientUserChangePassword
bool Locator::clientUserChangePassword(std::string newpassword)
{
  std::cout << "--> Do clientUserChangePassword. \n"
            << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "clientUserChangePassword";
  request["params"]["query"]["sessionId"] = session_id_;
  request["params"]["query"]["userName"] = username_;
  request["params"]["query"]["newUserPassword"] = newpassword;

  // post JSON info
  std::string str_url = "http://" + host_name_ + ":8080";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);
  // std::cout << "changepassword response: \n " << str_response << std::endl;

  // get error or necessary info
  Json json;
  try
  {
    json = Json::parse(str_response);
    int response_code = json["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    clientUserChangePassword Success.\n"
                << std::endl;
      std::cout << "   newUserPassword is " << request["params"]["query"]["newUserPassword"] << "\n"
                << std::endl;
      return true;
    }
    else
    {
      std::cout << "    clientUserChangePassword Failed! \n"
                << std::endl;
      std::cout << "    clientUserChangePassword response: " << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 9.1.1 serverMapGetInfo
bool Locator::serverMapGetInfo(std::string map_name)
{
  std::cout << "--> Do serverMapGetInfo \n"
            << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "serverMapGetInfo";
  request["params"]["query"]["sessionId"] = session_id_;
  request["params"]["query"]["serverMapName"] = map_name;

  // post json info
  std::string str_url = "http://" + host_name_ + ":8082";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // get error or necessary info
  Json json_response;
  try
  {
    // std::cout<<str_response<<std::endl;
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << std::setw(4) << json_response << std::endl;
      return true;
      // btw: "fingerprint", "type" and "level" (from response code) are not used at LLS release 1.1
      // std::cout << "    nameofmap is " << map_name << "\n"
      //           << std::endl;
      // if (json_response["result"]["response"]["loaded"] == true)
      // {
      //   std::cout << "        the map is loaded into the Map Server’s memory \n"
      //             << std::endl;
      // }
      // else
      // {
      //   std::cout << "        the map is not loaded into the Map Server’s memory \n"
      //             << std::endl;
      // }

      // if (json_response["result"]["response"]["createdAt"]["valid"] == true)
      // {
      //   double unix_timestamps = json_response["result"]["response"]["createdAt"]["time"].get<double>();
      //   time_t diagnos_info_time = unix_timestamps / 1000000;
      //   std::cout << "        createdAt（UTC/GMT+08:00）:  " << ctime(&diagnos_info_time) << std::endl;
      // }
      // else if (json_response["result"]["response"]["createdAt"]["valid"] == false)
      // {
      //   std::cout << "         map is not created, createdAt valid is false \n"
      //             << std::endl;
      // }

      // if (json_response["result"]["response"]["updatedAt"]["valid"] == true)
      // {
      //   double unix_timestamps = json_response["result"]["response"]["updatedAt"]["time"].get<double>();
      //   time_t diagnos_info_time = unix_timestamps / 1000000;
      //   std::cout << "        updatedAt（UTC/GMT+08:00）:  " << ctime(&diagnos_info_time) << std::endl;
      // }
      // else if (json_response["result"]["response"]["updatedAt"]["valid"] == false)
      // {
      //   std::cout << "        map is not updated,updatedAt valid is false \n " << std::endl;
      // }

      // if (json_response["result"]["response"]["sentAt"]["valid"] == true)
      // {
      //   double unix_timestamps = json_response["result"]["response"]["sentAt"]["time"].get<double>();
      //   time_t diagnos_info_time = unix_timestamps / 1000000;
      //   std::cout << "        sentAt（UTC/GMT+08:00）:   " << ctime(&diagnos_info_time) << std::endl;
      // }
      // else if (json_response["result"]["response"]["sentAt"]["valid"] == false)
      // {
      //   std::cout << "        map is not sent, sentAt valid is false \n"
      //             << std::endl;
      // }

      // if (json_response["result"]["response"]["receivedAt"]["valid"] == true)
      // {
      //   double unix_timestamps = json_response["result"]["response"]["receivedAt"]["time"].get<double>();
      //   time_t diagnos_info_time = unix_timestamps / 1000000;
      //   std::cout << "        receivedAt（UTC/GMT+08:00）:  " << ctime(&diagnos_info_time) << std::endl;
      // }
      // else if (json_response["result"]["response"]["receivedAt"]["valid"] == false)
      // {
      //   std::cout << "        map is not received, receivedAt valid is false \n"
      //             << std::endl;
      // }

      // std::cout << "    serverMapGetInfo Success. \n"
      //           << std::endl;
      // return true;
    }
    else
    {
      std::cout << "    serverMapGetInfo Failed." << std::endl;
      std::cout << "    serverMapGetInfo response: \n"
                << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 9.1.2 serverMapList
bool Locator::serverMapList()
{
  std::cout << "--> Do serverMapList \n"
            << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "serverMapList";
  request["params"]["query"]["sessionId"] = session_id_;

  // post json info
  std::string str_url = "http://" + host_name_ + ":8082";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "Map List from server: "
                << "\n"
                << std::endl;
      auto key_value = json_response["result"]["response"]["serverMapNames"];
      for (int i = 0; i < key_value.size(); i = i + 1)
      {
        std::string mapname = key_value[i].get<std::string>();
        std::cout << "    " << mapname << std::endl;
      }
      std::cout << std::endl;
      std::cout << "serverMapList Success. \n"
                << std::endl;

      return true;
    }
    else
    {
      std::cout << "    serverMapList Failed." << std::endl;
      std::cout << "    serverMapList response: \n"
                << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 9.1.5 serverMapGetMap
bool Locator::serverMapGetMap(std::string server_map_name)
{
  std::cout << "--> Do serverMapGetMap" << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "serverMapGetMap";
  request["params"]["query"]["sessionId"] = session_id_;
  request["params"]["query"]["serverMapName"] = server_map_name;

  // post json info
  std::string str_url = "http://" + host_name_ + ":8082";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);
  // std::cout<<" send data is   "<<  request.dump()<< std::endl;
  // get error or necessary info
  // std::cout<< str_response<<std::endl;
  Json json_response;

  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::string content = "";
      content = json_response["result"]["response"]["pointCloud"]["content"];
      std::string point_cloud_str = base64_decode(content);

      Size point_cloud_size = json_response["result"]["response"]["pointCloudSize"];
      std::cout << "pointCloudSize: " << point_cloud_size << std::endl;
      std::vector<char> buffer(point_cloud_str.begin(), point_cloud_str.end());

      // Convert the byte string to a point cloud
      pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
      cloud->width = buffer.size() / sizeof(float) / 2;
      cloud->height = 1;
      cloud->points.resize(cloud->width * cloud->height);

      for (std::size_t i = 0; i < cloud->points.size(); ++i)
      {
        float x = *reinterpret_cast<float *>(&buffer[i * 8]);
        float y = *reinterpret_cast<float *>(&buffer[i * 8 + 4]);
        float z = 0;
        cloud->points[i] = pcl::PointXYZ(x, y, z);
      }

      // Save the point cloud to a PCD file
      if (pcl::io::savePCDFileBinary("./build/" + server_map_name + ".pcd", *cloud) == -1)
      {
        std::cerr << "Failed to save pcd file." << std::endl;
        return 1;
      }

      // Create a PCLVisualizer object
      // pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Point Cloud Viewer"));
      pcl::visualization::PCLVisualizer viewer("Point Cloud Viewer");

      // Set the background color to white
      viewer.setBackgroundColor(0, 0, 0);

      // Add the point cloud to the viewer
      viewer.addPointCloud(cloud);

      // Set the point cloud color to red
      viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 1, 1, "cloud");

      // Set the point size to 2 pixels
      viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cloud");

      // Display the point cloud
      // while (!viewer.wasStopped())
      // {
      //   viewer.spinOnce();
      // }
      // viewer->pcl::visualization::PCLVisualizer::~PCLVisualizer();
      viewer.spin();

      return true;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
  catch (...)
  {
    std::cerr << "Unknown exception caught." << std::endl;
  }
  return false;
}

// 9.1.7 serverMapGetImageWithResolution
bool Locator::serverMapGetImageWithResolution(std::string server_map_name, double resolution)
{
  std::cout << "--> Do serverMapGetImageWithResolution \n"
            << std::endl;

  // set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "serverMapGetImageWithResolution";
  request["params"]["query"]["sessionId"] = session_id_;
  request["params"]["query"]["serverMapName"] = server_map_name;
  request["params"]["query"]["resolution"] = resolution; // pixel/m

  // post json info
  std::string str_url = "http://" + host_name_ + ":8082";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);
  // std::cout<<" send data is   "<<  request.dump()<< std::endl;
  // get error or necessary info
  // std::cout<< str_response<<std::endl;
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::string mapcode = "";
      mapcode = json_response["result"]["response"]["image"]["content"];
      std::string img_decode64 = base64_decode(mapcode);
      std::fstream f2;
      std::string output_map_name = server_map_name + "_resolution_" + std::to_string(resolution) + ".png";
      f2.open("./build/" + output_map_name, std::ios::out | std::ios::binary);
      f2 << img_decode64;
      f2.close();
      std::cout << "serverMapGetImageWithResolution Success."
                << std::endl;
      return true;
    }
    else if (response_code == 9)
    {
      std::cout << "serverMapGetImageWithResolution Failed! (response_code ==9)" << std::endl;
      std::cout << "serverMapGetImageWithResolution response: "
                << str_response << std::endl;
      std::cout << "improper resolution, unit is x pixel/m (try 20?)."
                << std::endl;
      return false;
    }
    else if (response_code == 11)
    {
      std::cout << "serverMapGetImageWithResolution Failed! (response_code ==12)" << std::endl;
      std::cout << "serverMapGetImageWithResolution response: \n"
                << str_response << std::endl;
      std::cout << "incorrect mape name . \n"
                << std::endl;
      return false;
    }
    else
    {
      std::cout << "serverMapGetImageWithResolution Failed." << std::endl;
      std::cout << "serverMapGetImageWithResolution response: \n"
                << str_response << std::endl;
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

// 10.1.1/10.1.5 supportReportCreateAndGetPath
bool Locator::supportReportCreateAndGetPath()
{
  std::cout << "--> Do supportReportCreate. \n"
            << std::endl;
  std::string reportname = "";

  // supportReportCreate set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "supportReportCreate";
  request["params"]["query"]["sessionId"] = session_id_;

  // post json info
  std::string str_url = "http://" + host_name_ + ":8084";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    supportReportCreate Success. \n"
                << std::endl;
      reportname = json_response["result"]["response"]["reportName"];
      std::cout << "    SupportReportName is " << json_response["result"]["response"]["reportName"] << "\n"
                << std::endl;
    }
    else
    {
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }

  std::cout << "--> Do supportReportGetPath. \n"
            << std::endl;
  str_response = "";

  // supportReportGetPath set json info
  Json request_getpath;
  request_getpath["id"] = id_++;
  request_getpath["jsonrpc"] = "2.0";
  request_getpath["method"] = "supportReportGetPath";
  request_getpath["params"]["query"]["sessionId"] = session_id_;
  request_getpath["params"]["query"]["reportName"] = reportname;
  // post json info
  str_url = "http://" + host_name_ + ":8084";
  HttpClient::HttpPost(str_url, request_getpath.dump(), str_response, 300);

  // get error or necessary info
  Json json_response_getpath;
  try
  {
    json_response_getpath = Json::parse(str_response);
    int response_code = json_response_getpath["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    supportReportGetPath Success. \n"
                << std::endl;
      std::cout << "    supportReport Path is " << json_response_getpath["result"]["response"]["reportNameUrl"] << "\n"
                << std::endl;
      return true;
    }
    else
    {
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

bool Locator::supportReportCreate()
{
  std::cout << "--> Do supportReportCreate. \n"
            << std::endl;
  std::string reportname = "";

  // supportReportCreate set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "supportReportCreate";
  request["params"]["query"]["sessionId"] = session_id_;

  // post json info
  std::string str_url = "http://" + host_name_ + ":8084";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);

  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    supportReportCreate Success. \n"
                << std::endl;
      reportname = json_response["result"]["response"]["reportName"];
      std::cout << "    SupportReportName is " << json_response["result"]["response"]["reportName"] << "\n"
                << std::endl;
      return true;
    }
    else
    {
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

bool Locator::supportReportGetPath(std::string report_name)
{
  std::cout << "--> Do supportReportGetPath. \n"
            << std::endl;
  std::string str_response = "";

  // supportReportGetPath set json info
  Json request_getpath;
  request_getpath["id"] = id_++;
  request_getpath["jsonrpc"] = "2.0";
  request_getpath["method"] = "supportReportGetPath";
  request_getpath["params"]["query"]["sessionId"] = session_id_;
  request_getpath["params"]["query"]["reportName"] = report_name;
  // post json info
  std::string str_url = "http://" + host_name_ + ":8084";
  HttpClient::HttpPost(str_url, request_getpath.dump(), str_response, 300);

  // get error or necessary info
  Json json_response_getpath;
  try
  {
    json_response_getpath = Json::parse(str_response);
    int response_code = json_response_getpath["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << "    supportReportGetPath Success. \n"
                << std::endl;
      std::cout << "    supportReport Path is " << json_response_getpath["result"]["response"]["reportNameUrl"] << "\n"
                << std::endl;
      return true;
    }
    else
    {
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

bool Locator::supportReportList()
{
  std::cout << "--> Do " << __func__ << std::endl;

  // supportReportCreate set json info
  Json request;
  request["id"] = id_++;
  request["jsonrpc"] = "2.0";
  request["method"] = "supportReportList";
  request["params"]["query"]["sessionId"] = session_id_;

  // post json info
  std::string str_url = "http://" + host_name_ + ":8086";
  std::string str_response;
  HttpClient::HttpPost(str_url, request.dump(), str_response, 300);
  std::cout << str_response << std::endl;
  // get error or necessary info
  Json json_response;
  try
  {
    json_response = Json::parse(str_response);
    int response_code = json_response["result"]["response"]["responseCode"];
    if (response_code == 0)
    {
      std::cout << __func__ << "Success." << std::endl;
      std::cout << json_response << std::endl;

      return true;
    }
    else
    {
      return false;
    }
  }
  catch (const std::exception &e)
  {
    std::cout << "Failed to parse JSON data: " << e.what() << std::endl;
    return false;
  }
}

int main(int argc, char **argv)
{
  // Locator session_locator_client("127.0.0.1", "admin", "admin_password");

  // session_locator_client.sessionLogin(8080);
  // session_locator_client.clientLocalizationSetSeed(-0.143275, 0.7882726, 4.78);
  // session_locator_client.sessionLogout(8080, session_locator_client.session_id_);

  // init
  Locator session_locator_server("127.0.0.1", "admin", "admin_password");

  int choice;
  std::string userInput;
  std::string map_name{""};
  double resolution{0.};

  while (true)
  {
    // Display menu options
    std::cout << "**** Options **************************" << std::endl;
    // std::cout << "721: Run sessionLogin" << std::endl;
    // std::cout << "722: Run sessionLogout" << std::endl;
    std::cout << "911: Run serverMapGetInfo" << std::endl;
    std::cout << "912: Run serverMapList" << std::endl;
    std::cout << "915: Run serverMapGetMap" << std::endl;
    std::cout << "917: Run serverMapGetImageWithResolution" << std::endl;
    std::cout << "1011: Run supportReportCreate" << std::endl;
    std::cout << "1014: supportReportList" << std::endl;
    std::cout << "0: Quit" << std::endl;
    std::cout << "Enter an option number: ";

    // Get user input
    std::cin >> userInput;
    try
    {
      choice = std::stoi(userInput);
    }
    catch (const std::exception &e)
    {
      std::cerr << "Error: " << e.what() << std::endl;
    }
    switch (choice)
    {
      // case 721:
      // {
      //   std::cout << "Enter communication port: " << std::endl;
      //   std::cin >> session_locator_server.port_;
      //   session_locator_server.sessionLogin(session_locator_server.port_);
      //   break;
      // }
      // case 722:
      //   if (!session_locator_server.session_id_.empty())
      //   {
      //     session_locator_server.sessionLogout(session_locator_server.session_id_);
      //   }
      //   break;

      // case 834:
      // {
      //   session_locator_server.sessionLogin(8080);
      //   session_locator_server.clientLocalizationSetSeed(-0.143275, 0.7882726, 4.78);
      //   session_locator_server.sessionLogout(8082, session_locator_server.session_id_);
      //   break;
      // }

    case 911:
    {
      session_locator_server.sessionLogin(8082);
      std::cout << "Enter map name: " << std::endl;
      std::cin >> map_name;
      session_locator_server.serverMapGetInfo(map_name);
      session_locator_server.sessionLogout(8082, session_locator_server.session_id_);
      break;
    }
    case 912:
    {
      session_locator_server.sessionLogin(8082);
      session_locator_server.serverMapList();
      session_locator_server.sessionLogout(8082, session_locator_server.session_id_);
      break;
    }
    case 915:
    {
      session_locator_server.sessionLogin(8082);
      std::cout << "Enter map name: ";
      std::cin >> map_name;
      session_locator_server.serverMapGetMap(map_name);
      session_locator_server.sessionLogout(8082, session_locator_server.session_id_);
      break;
    }
    case 917:
    {
      session_locator_server.sessionLogin(8082);
      std::cout << "Enter map name: " << std::endl;
      std::cin >> map_name;
      std::cout << "Resolution, pixels per meter: ";
      std::cin >> resolution;
      session_locator_server.serverMapGetImageWithResolution(map_name, resolution);
      session_locator_server.sessionLogout(8082, session_locator_server.session_id_);
      break;
    }
    case 1011:
    {
      session_locator_server.sessionLogin(8086);
      session_locator_server.supportReportCreate();
      session_locator_server.sessionLogout(8086, session_locator_server.session_id_);
      break;
    }
    case 1014:
    {
      session_locator_server.sessionLogin(8082);
      session_locator_server.supportReportList();
      session_locator_server.sessionLogout(8082, session_locator_server.session_id_);
      break;
    }
    case 0:
      return 0;
    default:
      std::cout << "Invalid choice. Please try again." << std::endl;
      break;
    }
  }

  return 0;

  // 7.2.1 sessionLogin
  // locator.sessionLogin(8080);

  // 7.3.1 diagnosticList
  // locator.diagnosticList();
  // locator.diagnosticClear();

  // 7.4.2 licensingFeatureGetHostId
  // locator.licensingFeatureGetHostId();
  // 7.4.3 licensingFeatureSet
  // locator.licensingFeatureSet("testfiles.bin");

  // 7.5.1 configList
  // locator.configList();
  // 7.5.2 configSet
  // locator.configSet_string("licensing.method","WIBUDONGLE");
  // locator.configSet_bool("config_laser.shall_mirror_scans",true);
  // locator.configSet_num("odometry_handler.laser_T_odo.x", -0.85);
  // std::vector<int> line_data = {3,4,5,6,1,1,2,5}; // line_data= {line1x_1,line1y_1,line1x_2,line1y_2,line2x_1,line2y_1,line2x_2,line2y_2} etc.
  // locator.configSet_array("config_laser.mask.min_range_line_data",line_data);

  // 8.1.3 clientRecordingStartVisualRecording
  // locator.clientRecordingStartVisualRecording("testfileName");
  // 8.1.4 clientRecordingStopVisualRecording
  // locator.clientRecordingStopVisualRecording();

  // 8.3.1 & 8.3.2 clientLocalizationStart & Stop
  // 如果 flag是 true 说明locate打开，那么要要关掉locate功能并返回false
  // locator.clientLocalizationSwitch(true);
  // std::cout << "Localization: " << local_flag << "\n";

  // sleep(2);
  // locator.clientLocalizationSwitch(local_flag);
  // std::cout << "Localization: " << local_flag << "\n";
  // sleep(2);
  // locator.clientLocalizationSwitch(local_flag);
  // std::cout << "Localization: " << local_flag << "\n";
  // sleep(2);
  // locator.clientLocalizationSwitch(local_flag);
  // std::cout << "Localization: " << local_flag << "\n";

  // // 8.3.4 clientLocalizationSetSeed
  // locator.clientLocalizationSetSeed(-0.143275, 0.7882726, 4.78);

  // 8.4.1 clientManualAlignStart
  // locator.clientManualAlignStart();
  // 8.4.2  clientManualAlignStop
  // locator.clientManualAlignStop();
  // 8.4.4 clientManualAlignSet
  // locator.clientManualAlignSet(10,5,0.8,"bosch_sha_jingwenmap");

  // 8.6.1 clientLaserMaskingStart
  // locator.clientLaserMaskingStart();
  // locator.clientLaserMaskingGetScan();
  // sleep(1);
  // locator.clientLaserMaskingStop();
  // 8.7.3 clientUserChangePassword
  // locator.clientUserChangePassword("123456");

  // locator.sessionLogin(8082);

  // 9.1.1serverMapGetInfo
  // locator.serverMapGetInfo("map");
  // 9.1.2 serverMapList
  // locator.serverMapList();
  // 9.1.5
  // locator.serverMapGetMap("map");
  // 9.1.7 serverMapGetImageWithResolution
  // locator.serverMapGetImageWithResolution("teeeest", 15);

  // 10.1.1/10.1.5 supportReportCreate and supportReportGetPath
  // locator.sessionLogin(8084);
  // locator.supportReportCreateAndGetPath();
}